package com.alipay.app.groupmeal.standard.ui;

import static com.alipay.app.groupmeal.standard.constant.ConfigConstant.onOffLine;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.alipay.app.groupmeal.standard.R;
import com.alipay.app.groupmeal.standard.base.BaseMVCActivity;
import com.alipay.app.groupmeal.standard.bean.AliPayResVo;
import com.alipay.app.groupmeal.standard.bean.FoodBean;
import com.alipay.app.groupmeal.standard.bean.SerialPortReceive;
import com.alipay.app.groupmeal.standard.constant.BaseConstant;
import com.alipay.app.groupmeal.standard.constant.ConfigConstant;
import com.alipay.app.groupmeal.standard.constant.SystemConsts;
import com.alipay.app.groupmeal.standard.event.EventManager;
import com.alipay.app.groupmeal.standard.http.bean.resp.Result;
import com.alipay.app.groupmeal.standard.offline.bean.OrderBean;
import com.alipay.app.groupmeal.standard.offline.manager.OrderDataManager;
import com.alipay.app.groupmeal.standard.receiver.NetworkChangeReceiver;
import com.alipay.app.groupmeal.standard.service.MqttService;
import com.alipay.app.groupmeal.standard.thread.TimeThread;
import com.alipay.app.groupmeal.standard.ui.b.function.FunctionPre;
import com.alipay.app.groupmeal.standard.ui.c.BindActivity;
import com.alipay.app.groupmeal.standard.ui.c.ReadCardActivity;
import com.alipay.app.groupmeal.standard.ui.c.SelectPayActivity;
import com.alipay.app.groupmeal.standard.ui.c.abcp.CPayingAbcpActivity2;
import com.alipay.app.groupmeal.standard.ui.c.abcp.CQuotaAuthActivity;
import com.alipay.app.groupmeal.standard.ui.b.util.DeviceInfoManager;
import com.alipay.app.groupmeal.standard.ui.b.util.NFCManager;
import com.alipay.app.groupmeal.standard.ui.b.util.WIth;
import com.alipay.app.groupmeal.standard.util.ActivityUtil;
import com.alipay.app.groupmeal.standard.util.ByteUtil;
import com.alipay.app.groupmeal.standard.util.HexDump;
import com.alipay.app.groupmeal.standard.util.SerialInputOutputManager;
import com.alipay.app.groupmeal.standard.util.SerialPortHelperUtil;
import com.alipay.app.groupmeal.standard.util.USBTransferUtil;
import com.alipay.app.groupmeal.standard.util.driver.ProbeTable;
import com.alipay.app.groupmeal.standard.util.driver.UsbSerialDriver;
import com.alipay.app.groupmeal.standard.util.driver.UsbSerialPort;
import com.alipay.app.groupmeal.standard.util.driver.UsbSerialProber;
import com.alipay.iot.bpaas.api.utils.StringUtil;
import com.alipay.sdk.abcphaima.AbcpHM;
import com.alipay.sdk.abcphaima.bean.ConfigData;
import com.alipay.sdk.util.LogUtil;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

import cn.wch.ch34xuartdriver.CH34xUARTDriver;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.internal.observers.BlockingBaseObserver;
import pl.com.salsoft.sqlitestudioremote.SQLiteStudioService;
import top.keepempty.sph.library.SerialPortConfig;
import top.keepempty.sph.library.SerialPortHelper;
import top.keepempty.sph.library.SphCmdEntity;
import top.keepempty.sph.library.SphResultCallback;

/**
 * 首页
 */
public class MainActivity extends BaseMVCActivity
        implements NetworkChangeReceiver.NetStateChangeObserver, NFCManager.OnReceiveNfcTagCallback, SerialInputOutputManager.Listener {

    private FunctionPre mFunctionPre;

    public static MainActivity mActivity;

    // NFC读卡
    private NFCManager mNFCManager;

    private enum UsbPermission { Unknown, Requested, Granted, Denied }
    private SerialInputOutputManager usbIoManager;
    private UsbSerialPort usbSerialPort;
    private UsbPermission usbPermission = UsbPermission.Unknown;

    private Handler mainLooper;
    private boolean connected = false;

    private static final String INTENT_ACTION_GRANT_USB = "com.gzdh.app.groupmeal.standard.GRANT_USB";
    private static final int WRITE_WAIT_MILLIS = 2000;
    private static final int READ_WAIT_MILLIS = 2000;

    private static final StringBuilder receiveText = new StringBuilder();

    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void onCreateBundle(@Nullable Bundle savedInstanceState) {
        super.onCreateBundle(savedInstanceState);
        SQLiteStudioService.instance().start(this);    //打开sqlite检测
        new Thread(new TimeThread()).start();
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (StringUtil.isEmpty(SystemConsts.getSystemConsts().getPosnum())) {
            new WIth(this).getPosInit();
        }
    }

    @Override
    protected void initView() {
        mActivity = this;
        mNFCManager = new NFCManager(this);
        mainLooper = new Handler(Looper.getMainLooper());
        SharedPreferences sysInfo = getSharedPreferences("sysCost", MODE_PRIVATE);
        String sysApi = sysInfo.getString("api", null);//读取username
        String abcpAppid = sysInfo.getString("abcpAppid", "");
        String abcpAppVersion = sysInfo.getString("abcpAppVersion", "");
        String logicGroupId = sysInfo.getString("logicGroupId", "");
        String devPsk = sysInfo.getString("devPsk", "");
        String tenantId = sysInfo.getString("tenantId", "");

        int successTime = sysInfo.getInt("successTime", 3);
        int expireTime = sysInfo.getInt("expireTime", 20);
        if (sysApi == null) {
            //跳转新页面设置
            BindActivity.startAct(this);
            finish();
            return;
        } else {
            ConfigConstant.BASE_API_URL = sysApi;
//            ConfigConstant.BASE_API_URL = "https://dcxt.gzknyy.com/mzsfj/";
            ConfigConstant.abcpAppId = abcpAppid;
            ConfigConstant.abcpAppVersion = abcpAppVersion;
            ConfigConstant.logicGroupID = logicGroupId;
            ConfigConstant.successTime = successTime;
            ConfigConstant.expireTime = expireTime;
            ConfigConstant.devPSK = devPsk;
            ConfigConstant.tenantId = tenantId;
        }
        //初始化ABCP SDK
        ConfigData configData = new ConfigData();
        configData.abcpAppId = ConfigConstant.abcpAppId;
        configData.abcpAppVersion = ConfigConstant.abcpAppVersion;
        configData.industryBizType = "business";
        configData.merchantId = ConfigConstant.merchantId;
        configData.merchantName = ConfigConstant.merchantName;
        configData.isvName = ConfigConstant.isvName;
        configData.partnerId = ConfigConstant.partnerId;
        configData.logicGroupID = ConfigConstant.logicGroupID;
        configData.uploadTimeOutSecs = ConfigConstant.uploadTimeOutSecs;
        configData.enableOfflineFace = ConfigConstant.enableOfflineFace;
        AbcpHM.getInstance().init(getApplication(), configData, isSuccess -> {
            LogUtil.d("abcp初始化回调：" + isSuccess);
        });
        startService(new Intent(this, MqttService.class));
    }

    @Override
    protected void initData() {
        NetworkChangeReceiver.registerReceiver(this);
        NetworkChangeReceiver.registerObserver(this);
        //connect();
        //方式二：通过SerialPortConfig设置相关串口参数
        SerialPortHelper serialPortHelper = SerialPortHelperUtil.getInstance().newSerialPortHelper(this);
        String command = "5A3C002B020000000000000000008096980064000000002E332E30302CD0A1C7E0B2CB26342E30302CBAECC9D5C8E2C6DB";
        serialPortHelper.addCommands(command.getBytes()); // 发送字节数组
    }

    private void connect() {
        UsbDevice device = null;
        UsbSerialDriver driver = null;
        UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        UsbSerialProber usbDefaultProber = UsbSerialProber.getDefaultProber();
        UsbSerialProber usbCustomProber = new UsbSerialProber(new ProbeTable());
        for(UsbDevice usbDevice : usbManager.getDeviceList().values()) {
            driver = usbDefaultProber.probeDevice(usbDevice);
            if(driver == null) {
                driver = usbCustomProber.probeDevice(usbDevice);
            }
            if(driver != null) {
                String name = driver.getClass().getSimpleName();
                if(name.equals(DeviceInfoManager.getSerialPortSelect())) {
                    device = usbDevice;
                    break;
                }
            }
        }
        if(device == null) {
            status("connection failed: device not found");
            return;
        }
        int portNum = DeviceInfoManager.getSerialPortNum();
        if(driver.getPorts().size() < portNum) {
            status("connection failed: not enough ports at device");
            return;
        }
        usbSerialPort = driver.getPorts().get(portNum);
        UsbDeviceConnection usbConnection = usbManager.openDevice(driver.getDevice());
        //检查是否有权限
        if(usbConnection == null && usbPermission == UsbPermission.Unknown && !usbManager.hasPermission(driver.getDevice())) {
            usbPermission = UsbPermission.Requested;
            int flags = PendingIntent.FLAG_IMMUTABLE;
            Intent intent = new Intent(INTENT_ACTION_GRANT_USB);
            intent.setPackage(getPackageName());
            PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(this, 0, intent, flags);
            usbManager.requestPermission(driver.getDevice(), usbPermissionIntent);
            return;
        }
        if(usbConnection == null) {
            if (!usbManager.hasPermission(driver.getDevice()))
                status("connection failed: permission denied");
            else
                status("connection failed: open failed");
            return;
        }

        try {
            usbSerialPort.open(usbConnection);
            try{
                usbSerialPort.setParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE);
            }catch (UnsupportedOperationException e){
                status("unsupport setparameters");
            }
            usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
            usbIoManager.start();
            status("connected");
            connected = true;
            send("hello");
            /*new Thread(() -> {
                while (true) {
                    read();
                }
            }).start();*/
        } catch (Exception e) {
            status("connection failed: " + e.getMessage());
            disconnect();
        }
    }

    private void disconnect() {
        connected = false;
        if(usbIoManager != null) {
            usbIoManager.setListener(null);
            usbIoManager.stop();
        }
        usbIoManager = null;
        try {
            usbSerialPort.close();
        } catch (IOException ignored) {}
        usbSerialPort = null;
    }

    private void send(String str) {
        if(!connected) {
            Toast.makeText(this, "not connected", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            byte[] data = (str + '\n').getBytes();
            SpannableStringBuilder spn = new SpannableStringBuilder();
            spn.append("send ").append(String.valueOf(data.length)).append(" bytes\n");
            spn.append(HexDump.dumpHexString(data)).append("\n");
            spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.blue2)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            //receiveText.append(spn);
            usbSerialPort.write(data, WRITE_WAIT_MILLIS);
        } catch (Exception e) {
            onRunError(e);
        }
    }

    private void read() {
        if(!connected) {
            Toast.makeText(this, "not connected", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            byte[] buffer = new byte[8192];
            int len = usbSerialPort.read(buffer, READ_WAIT_MILLIS);
            receive(Arrays.copyOf(buffer, len));
        } catch (IOException e) {
            // when using read with timeout, USB bulkTransfer returns -1 on timeout _and_ errors
            // like connection loss, so there is typically no exception thrown here on error
            status("connection lost: " + e.getMessage());
            disconnect();
        }
    }

    private void receive(byte[] data) {
        SpannableStringBuilder spn = new SpannableStringBuilder();
        if(data.length > 0) {
            String hexString = HexDump.toHexString(data);
            spn.append(hexString);
            receiveText.append(spn.toString().trim());
            if(spn.toString().endsWith("DB")) {
                System.out.println(receiveText);
                String string = receiveText.substring(receiveText.length() - 12, receiveText.length() - 4);
                System.out.println(string);
                byte[] temp = ByteUtil.hexStringToByte(string);
                byte[] byteArray = new byte[temp.length];
                for (int i = 0; i < temp.length; i++) {
                    byteArray[i] = temp[temp.length - 1 - i];
                }
                String finalString = HexDump.toHexString(byteArray);
                BigDecimal amount = new BigDecimal(Integer.parseInt(finalString, 16)).divide(new BigDecimal(100));
                System.out.println(amount);
                if (!ActivityUtil.isActivityRunning(this, "com.alipay.app.groupmeal.standard.ui.c.abcp.CPayingAbcpActivity2")) {
                    // activity未在运行，可以选择停止服务或处理其他逻辑
                    Intent intent = new Intent(mActivity, CPayingAbcpActivity2.class);
                    intent.putExtra("amount", amount.toPlainString());
                    mActivity.startActivity(intent);
                }
                receiveText.delete(0, receiveText.length());
            }
        }
    }

    void status(String str) {
        SpannableStringBuilder spn = new SpannableStringBuilder(str+'\n');
        spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.blue2)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        //receiveText.append(spn);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if(!connected && (usbPermission == UsbPermission.Unknown || usbPermission == UsbPermission.Granted)) {
            mainLooper.post(this::connect);
        }
        showPresentation(mFunctionPre);
        if (mFunctionPre != null) {
            setBScreenMode();
        }
        mNFCManager.dispatch();
        List<OrderBean> list = OrderDataManager.getInstance().queryAllNotPosted();
        LogUtil.i("未支付订单数: " + ((list == null) ? 0 : list.size()));
        List<OrderBean> failed = OrderDataManager.getInstance().queryAllFailed();
        LogUtil.i("同步失败订单数: " + ((failed == null) ? 0 : failed.size()));
        if (!USBTransferUtil.isOpen) {
            USBTransferUtil.driver = new CH34xUARTDriver(
                    (UsbManager) getSystemService(Context.USB_SERVICE), mActivity,
                    ACTION_USB_PERMISSION);
            int retval = USBTransferUtil.driver.ResumeUsbPermission();
            if (retval == 0) {

                retval = USBTransferUtil.driver.ResumeUsbList();
                if (retval == -1) {
                    USBTransferUtil.driver.CloseDevice();
                } else if (retval == 0) {
                    if (USBTransferUtil.driver.mDeviceConnection != null) {
                        if (!USBTransferUtil.driver.UartInit()) {//对串口设备进行初始化操作
                            return;
                        }
                        USBTransferUtil.isOpen = true;
                        new readThread().start();//开启读线程读取串口接收的数据
                    }
                }
            }
        }

    }

    @Override
    protected void onPause() {
        super.onPause();
        mNFCManager.cancelDispatch();

    }

    private static final String ACTION_USB_PERMISSION = "cn.wch.wchusbdriver.USB_PERMISSION";


    @Override
    public void initPresentation() {
        super.initPresentation();
        if (mDisplay != null) {
            mFunctionPre = new FunctionPre(this, mDisplay);
            mFunctionPre.setFunctionPreListener(new FunctionPre.FunctionPreListener() {
                @Override
                public void awaitPay(String amount, boolean isFree, boolean isCard) {
//                    UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
//                    HashMap<String, UsbDevice> usbDeviceList = usbManager.getDeviceList();
//                    for (UsbDevice usbDevice : usbDeviceList.values()) {
//                        int vid = usbDevice.getVendorId();
//                        int pid = usbDevice.getProductId();
//
//                        // 打印 VID 和 PID
//                        Log.d("USB Info", "Vendor ID (VID): " + vid);
//                        Log.d("USB Info", "Product ID (PID): " + pid);
//                        Log.d("USB Info", "Name:" + usbDevice.getDeviceName());
//                        Log.d("USB Info", "Device" + usbDevice.getProductName());
//                        Log.d("USB Info", "String" + usbDevice.toString());
//
//
//                    }

//                    if (!isOpen) {

//                    } else {
//                        isOpen = false;
//                        try {
//                            Thread.sleep(200);
//                        } catch (InterruptedException e) {
//                            // TODO Auto-generated catch block
//                            e.printStackTrace();
//                        }
//                        driver.CloseDevice();
//                    }


                    if (onOffLine) {
//                        CPayingAbcpActivity2.startActForAbcp(mActivity, amount);
                        Intent intent = new Intent(mActivity, CPayingAbcpActivity2.class);
                        intent.putExtra("amount", amount);
                        mActivity.startActivity(intent);
                    } else {
                        SelectPayActivity.startAct(mActivity, amount);
                    }
//                    SelectPayActivity.startAct(mActivity, amount);

//                    SelectPayActivity.startAct(mActivity, amount);
//                    if (isCard) {
//                        //开始唤起刷卡支付界面
//                        CPayAbcpActivity.startActAbcp(mActivity, amount);
//                    } else {
//                        //isFree 是否自由模式
//                        setClearAmount(false);
//                        //启动人脸支付
//                    }
//                        CPayingAbcpActivity.startActForAbcp(mActivity, amount);
                }
            });
            registerPresentation(mFunctionPre);
            mFunctionPre.setUserOrderListener(() -> CQuotaAuthActivity.startActAbcp(mActivity));
            mFunctionPre.setInitDevice(type -> {
                if (type == 1) {
                    //解绑
                    SharedPreferences userInfo = getSharedPreferences("sysCost", MODE_PRIVATE);
                    SharedPreferences.Editor editor = userInfo.edit();
                    editor.putString("api", null);
                    editor.commit();
                }
                BindActivity.startAct(this);
                finish();
            });
        }
    }

    @Override
    public void onNewData(byte[] data) {
        mainLooper.post(() -> {
            receive(data);
        });
    }

    @Override
    public void onRunError(Exception e) {
        mainLooper.post(() -> {
            status("connection lost: " + e.getMessage());
            disconnect();
        });
    }

    private class readThread extends Thread {

        public void run() {

            byte[] buffer = new byte[4096];

            while (true) {

                Message msg = Message.obtain();
                if (!USBTransferUtil.isOpen) {
                    break;
                }
//                int length = driver.ReadData(buffer, 4096);
//                if (length > 0) {
//                    String recv = toHexString(buffer, length);		//以16进制输出
////					String recv = new String(buffer, 0, length);		//以字符串形式输出
//                    msg.obj = recv;
//                    handler.sendMessage(msg);
//                }
            }
        }
    }

    @Override
    public boolean onKeyEventBack(KeyEvent event) {
        if (mFunctionPre.isShowing()) {
            return mFunctionPre.dispatchKeyEvent(event);
        }
        return super.onKeyEventBack(event);
    }

    @Override
    public boolean onKeyEventEnter(KeyEvent event) {
        if (mFunctionPre != null && mFunctionPre.isShowing())
            return mFunctionPre.dispatchKeyEvent(event);
        return super.onKeyEventEnter(event);
    }

    @Override
    public boolean onKeyEventFunction(KeyEvent event) {
        if (mFunctionPre != null) {
            return mFunctionPre.onKeyEventFunction(event);
        }
        return super.onKeyEventFunction(event);
    }

    @Override
    public boolean onKeyEventNum(KeyEvent event) {
        if (mFunctionPre != null && mFunctionPre.isShowing()) {
            return mFunctionPre.dispatchKeyEvent(event);
        }
        return super.onKeyEventNum(event);
    }

    @Override
    public boolean onKeyEventSetting(KeyEvent event) {
        return super.onKeyEventSetting(event);
    }

    @Override
    public boolean onKeyEventUpAndDown(KeyEvent event) {
        if (mFunctionPre != null && mFunctionPre.isShowing()) {
            //当副屛启用时，直接通过副屛来分发按键事件
            return mFunctionPre.dispatchKeyEvent(event);
        }
        return super.onKeyEventUpAndDown(event);
    }

    @Override
    protected void dissmissPresnetation() {
        if (mFunctionPre != null)
            mFunctionPre.dismiss();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        NetworkChangeReceiver.unRegisterReceiver(this);
        AbcpHM.getInstance().removeIpcListener();
        mNFCManager.onDestroy();
        if (mFunctionPre != null) {
            mFunctionPre.dismiss();
        }
        unRegPresentation(mFunctionPre);
    }

    /**
     * 设置b屏 金额收款页面
     */
    private void setBScreenMode() {
        if (BaseConstant.CASHIER_MODE.MODE_FREE.equals(DeviceInfoManager.getCashierMode())) {
            //自由金额模式
            mFunctionPre.showInputAmount();
        }
        if (BaseConstant.CASHIER_MODE.MODE_FIXED.equals(DeviceInfoManager.getCashierMode())) {
            //固定金额模式
            mFunctionPre.showFixedAmount();
        }
        if (BaseConstant.CASHIER_MODE.MODE_HEXIAO.equals(DeviceInfoManager.getCashierMode())) {
            //自由金额模式
            mFunctionPre.showHexiaoAmount();
        }
    }

    public void setClearAmount(boolean clearAmount) {
        if (mFunctionPre != null) {
            mFunctionPre.setClearAmount(clearAmount);
        }
    }

    @Override
    public void onDisconnect() {

    }

    @Override
    public void onMobileConnect() {
        postData();
    }

    @Override
    public void onWifiConnect() {
        postData();
    }

    private void postData() {
        //同步本地未支付的订单
        List<OrderBean> list = OrderDataManager.getInstance().queryAllNotPosted();
        LogUtil.i("未支付订单数: " + ((list == null) ? 0 : list.size()));
        if (list != null && !list.isEmpty()) {
            for (OrderBean orderBean : list) {
                LogUtil.i("未支付订单: " + orderBean.toString());
//                new WIth(this).uploadOrder(orderBean.getAmount(), orderBean.getTradeNo(),
//                        orderBean.getCreateTime(), StringUtils.trimToEmpty(orderBean.getAuthCode()),
//                        orderBean.getCardno(), new BlockingBaseObserver<Result<String>>() {
//                            @Override
//                            public void onNext(@NonNull Result<String> stringResult) {
//                                OrderDataManager.getInstance().upLoadSuccess(orderBean);
//                            }
//
//                            @Override
//                            public void onError(@NonNull Throwable e) {
//                                e.printStackTrace();
//                            }
//                        });
                new WIth(this).cardPayV2(orderBean.getAmount(), orderBean.getAuthCode(),
                        orderBean.getTradeNo(), orderBean.getTradeNo(), 1, orderBean.getCreateTime(), new BlockingBaseObserver<Result<AliPayResVo>>() {
                            @Override
                            public void onNext(@NonNull Result<AliPayResVo> stringResult) {
                                OrderDataManager.getInstance().upLoadSuccess(orderBean);
                            }

                            @Override
                            public void onError(@NonNull Throwable e) {

                            }
                        });
            }
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        mNFCManager.receiveTag(intent);
    }

    @Override
    public void onReceiveNfcTag(String tag) {
        //正在支付页面，开始刷卡支付
        System.out.println("刷卡:打开新页面" + tag);
        ReadCardActivity.startAct(mActivity, tag);
    }

    @Override
    public void onEvent(Object message) {
        super.onEvent(message);
        if (message instanceof EventManager.tongbuOrder) {
            postData();
        }
    }
}